﻿namespace DimensionsHelper.Client.WinUi.ViewModels;

public partial class TaskInformationViewModel : ObservableRecipient, IRecipient<IProjectViewModel>, INavigationAware
{
    private readonly IProjectTaskService _projectTaskService;


    public TaskInformationViewModel(IProjectTaskService projectTaskService)
    {
        _projectTaskService = projectTaskService;
    }


    [ObservableProperty]
    public partial IProjectTask? Selected
    {
        get;
        set;
    }


    public IEnumerable<IProjectTask> Tasks => _projectTaskService.Tasks;

    public void Receive(IProjectViewModel message)
    {
        IProjectTask projTask = _projectTaskService.Allocate(message.Section, true);
        Selected = projTask;
        Task task = message.BuildTask(projTask, projTask.CancellationToken);
        task.ContinueWith(t =>
        {
            if (t.IsFaulted)
            {
                if (t.Exception != null)
                {
                    App.ShowErrorNotification(t.Exception.Message,
                        typeof(TaskInformationViewModel), projTask.Id);
                }

                return;
            }

            if (t.IsCanceled && App.NotifyWhenTaskFinished())
            {
                App.ShowNotification(message.Section, "AppTaskCanceledMessage".GetLocalized(),
                    typeof(TaskInformationViewModel), projTask.Id);
            }
        });
        projTask.StartTask(task);
        App.MainWindow.DispatcherQueue.TryEnqueue(() =>
        {
            App.GetService<INavigationService>().NavigateTo(typeof(TaskInformationViewModel).FullName!, projTask.Id);
        });
    }


    public void RegisterProjectTaskChangedHandler(NotifyCollectionChangedEventHandler handler)
    {
        if (_projectTaskService.Tasks is INotifyCollectionChanged observable)
        {
            observable.CollectionChanged -= handler;
            observable.CollectionChanged += handler;
        }
    }


    #region INavigationAware

    public void OnNavigatedTo(object parameter)
    {
        if (parameter is not string taskName)
        {
            return;
        }

        IProjectTask? task = Tasks.FirstOrDefault(t => t.Id.Equals(taskName));

        if (task == null)
        {
            return;
        }

        Selected = task;
        App.BringToFront();
    }

    public void OnNavigatedFrom() => EnsureItemSelected();

    public void EnsureItemSelected() => Selected ??= Tasks.First();

    #endregion
}